﻿using System;
using System.Threading;
using UnityEngine;

namespace JH
{
    /// <summary>
    ///  Tween动画的具体实现类
    /// </summary>
    public static class JTween
    {
        /// <summary>
        ///  用来方便调用的扩展方法
        /// </summary>
        /// <inheritdoc cref="Tween{T}"/>
        public static  JTask Tween<TExtension, T>(this TExtension _, T startValue, T endValue, Action<T> setValue,
            float duration, CancellationToken cancelToken, Ease ease = Ease.Linear)
        {
            return Tween(startValue, endValue, setValue, duration, cancelToken, ease);
        }

        /// <summary>
        ///  缓动到目标值
        /// </summary>
        /// <param name="startValue">起始值</param>
        ///  <param name="endValue">结束值</param>
        ///  <param name="setValue">设置值的方法</param>
        ///  <param name="duration">持续时间</param>
        ///  <param name="cancelToken">取消令牌</param>
        ///  <param name="ease">缓动类型</param>
        public static async JTask Tween<T>(T startValue, T endValue, Action<T> setValue, float duration,
            CancellationToken cancelToken, Ease ease = Ease.Linear)
        {
            //如果参数为空，抛出异常
            if (setValue == null) throw new ArgumentNullException();

            // 如果持续时间小于等于0，直接返回
            if (duration <= 0)
            {
                setValue(endValue);
                return;
            }

            // 保险起见，直接返回主线程
            await JTask.SwitchToMainThread(cancelToken);

            // 计时器
            float timer = 0;

            // 缓动
            while (timer <= duration)
            {
                // 计算插值
                float t = timer / duration;

                // 获取缓动值
                T value = EaseFunctionNumeric.Tween(startValue, endValue, ease, t);

                // 设置值
                setValue(value);

                // 更新计时器
                timer += Time.deltaTime;
                
                // 等待一帧
                await JTask.Yield(cancelToken);
            }

            // 设置最终值
            setValue(endValue);
        }
    }
}